import { CommandDialogPlacement } from '@amcax/base';
import { CloseOutlined, RightOutlined, UpOutlined } from '@ant-design/icons';
import { useUpdateEffect } from 'ahooks';
import React, { useEffect, useRef, useState } from 'react';
import Draggable from 'react-draggable';
import { Icon } from '../../common/components';
import { StyledAnimte, StyledLayout } from './styled';
import { BoxProps } from './types';

const ags = {
  left: 0,
  right: 0,
  bottom: 0,
  top: 0,
};
type Position = {
  x: number;
  y: number;
};
// 拖拽容器里的content
export const Box = ({
  title,
  titleIcon,
  onClose,
  disabled,
  bodyClassName,
  children,
  width = '320px',
  placement = 'right',
  defaultPosition = { x: 340, y: 120 },
  ...rest
}: BoxProps) => {
  const draggableRef = useRef<HTMLDivElement>(null);
  const boxRef = useRef<HTMLDivElement>(null);
  const [bounds, setBounds] = useState(ags);
  const [newStatus, setNewStatus] = useState({
    isOverLeft: false,
    isOverRight: false,
  });
  const [position, setPosition] = useState(
    defaultPosition ?? {
      x: 0,
      y: 0,
    },
  );
  // 动态计算边界限制
  const calculateBounds = () => {
    if (!draggableRef.current) return;

    const elementWidth = draggableRef.current.offsetWidth;
    const elementHeight = draggableRef.current.offsetHeight;
    const viewportWidth = window.innerWidth;
    const viewportHeight = window.innerHeight;

    setBounds({
      left: expand ? 0 : viewportWidth - elementHeight,
      right: viewportWidth - (expand ? elementWidth : elementHeight),
      top: expand ? 0 : elementWidth,
      bottom: viewportHeight - elementHeight + (expand ? 0 : elementHeight),
    });
  };
  // 初始化计算 & 窗口大小监听
  useEffect(() => {
    calculateBounds();
    window.addEventListener('resize', calculateBounds);
    if (!defaultPosition) {
      const vWidth = window.innerWidth;
      const vHeight = window.innerHeight;
      const rectBox = boxRef.current?.getBoundingClientRect();
      setPosition(getInitPosition(placement, { vWidth, vHeight, rectBox }));
    }
    return () => window.removeEventListener('resize', calculateBounds);
  }, []);

  const [open, setOpen] = useState(true);
  const [expand, setExpand] = useState(true);

  const handleMouseEvent = (e: React.MouseEvent) => {
    // 中键的 button 值为 1
    if (e.button === 1) {
      setOpen(!open);
      e.preventDefault(); // 阻止浏览器默认中键行为（如自动滚动）
    }
  };
  // 拖动事件处理
  const handleDrag = () => {
    // 获取元素当前视口位置
    checkBoundary();
  }; // 获取窗口右边界坐标
  const getRightBoundary = () => window.innerWidth;
  const checkBoundary = () => {
    if (!draggableRef.current) return;
    // 获取元素当前视口位置
    const rect = draggableRef.current?.getBoundingClientRect();
    setNewStatus({
      isOverLeft: rect.left <= 0,
      isOverRight: rect.right >= getRightBoundary(),
    });
  };

  useUpdateEffect(() => {
    calculateBounds();
    const vWidth = window.innerWidth;
    const rectBox = boxRef.current?.getBoundingClientRect();
    setPosition((state) => ({
      ...state,
      x: vWidth - (expand ? rectBox.width : rectBox.height),
    }));
    expand && setOpen(true);
  }, [expand]);
  return (
    <Draggable
      position={position}
      onDrag={handleDrag}
      bounds={bounds}
      onStop={(e, data) => setPosition({ x: data.x, y: data.y })}
      handle='.drag-handler'>
      <StyledAnimte>
        <StyledLayout
          className={`animate__animated animate__fadeInUp animate__faster ${expand && 'box-expand'}`}>
          <div
            ref={boxRef}
            className='box'
            style={{ width: expand ? width : '' }}>
            <div
              style={{ opacity: disabled ? 0.6 : 1 }}
              ref={draggableRef}
              className={`title-bar ${expand ? '' : 'max-content title-bar-expand'}`}
              onMouseDown={handleMouseEvent}>
              <div
                className={`${!disabled && 'drag-handler'}`}
                style={{ width: expand ? width : '' }}>
                {rest.customizeTitle ?? (
                  <div
                    style={{ display: 'flex' }}
                    className={`${expand ? '' : 'max-content'}`}>
                    <Icon
                      tabIndex={0}
                      style={{
                        fontSize: '20px',
                        marginRight: '5px',
                      }}
                      name={titleIcon}
                    />
                    <span className={`title`}>{title}</span>
                  </div>
                )}
              </div>
              {newStatus.isOverRight ? (
                <button
                  className='close-button'
                  onClick={() => setExpand(!expand)}>
                  {expand ? (
                    <RightOutlined style={{ fontSize: '14px' }} />
                  ) : (
                    <UpOutlined style={{ fontSize: '14px' }} />
                  )}
                </button>
              ) : (
                onClose && (
                  <button
                    className='close-button'
                    disabled={disabled}>
                    <CloseOutlined
                      style={{ fontSize: '14px' }}
                      onClick={onClose}
                    />
                  </button>
                )
              )}
            </div>
            <div
              className={bodyClassName ?? 'w-full mt-[-10px]'}
              style={{ display: open && expand ? 'block' : 'none' }}>
              {children}
            </div>
          </div>
        </StyledLayout>
      </StyledAnimte>
    </Draggable>
  );
};
type PositionType = { [key in CommandDialogPlacement]: Position };
function getInitPosition(
  placement: CommandDialogPlacement,
  { vWidth, vHeight, rectBox },
): Position {
  const positionX = {
    start: 0,
    center: (vWidth - rectBox.width) / 2,
    end: vWidth - rectBox.width,
  };
  const positionY = {
    start: 0,
    center: (vHeight - rectBox.height) / 2,
    end: vHeight - rectBox.height,
  };
  const position: PositionType = {
    top: { x: positionX.center, y: 0 },
    bottom: { x: positionX.center, y: positionY.end },
    left: { x: 0, y: positionY.center },
    right: { x: positionX.end, y: positionY.center },
    center: { x: positionX.center, y: positionY.center },
    topLeft: { x: 0, y: 0 },
    topRight: { x: positionX.end, y: 0 },
    bottomLeft: { x: 0, y: positionY.end },
    bottomRight: { x: positionX.end, y: positionY.end },
  };
  return position[placement];
}
